]> dgit.raspbian.org Git - pyqt6.git/commitdiff
Support for Python v3.15
authorPhil Thompson <phil@riverbankcomputing.com>
Mon, 13 Jul 2026 15:01:40 +0000 (16:01 +0100)
committerDmitry Shachnev <mitya57@debian.org>
Mon, 21 Sep 2026 07:40:53 +0000 (10:40 +0300)
The project can now be built with Python v3.15 (where the limited ABI
version targeted will be v3.13).

(cherry picked from commit 04c516de9e360ccea2407d5d3a72de3df161ceab)

Gbp-Pq: Name Support-for-Python-v3.15.patch

project.py
qpy/QtCore/qpycore_pyqtproperty.cpp
qpy/QtCore/qpycore_pyqtslot.cpp
qpy/QtCore/qpycore_qobject_helpers.cpp

index 5af031773287dd041599de37d768b4e507799639..5d9a52720f9d8892f62246eff2839033e0e0611c 100644 (file)
@@ -105,6 +105,14 @@ del find_qt
 
         return dunder_init
 
+    def get_limited_abi_version(self):
+        """ Return the version number of the limited ABI to use. """
+
+        # We use PyWeakref_GetObject() which was removed from the limited API
+        # in Python v3.15.  It's replacement, PyWeakref_GetRef() was added to
+        # the limited ABI in Python v3.13.
+        return (3, 13, 0) if sys.hexversion >= 0x030f0000 else None
+
     def get_options(self):
         """ Return the sequence of configurable options. """
 
index da696652cce9ef6e3db2f8dfd7220e371564aeb9..3892231b71baa1a069509ccbb08511004f819c6f 100644 (file)
@@ -511,7 +511,7 @@ static PyObject *pyqtProperty_reset(PyObject *self, PyObject *reset)
 static qpycore_pyqtProperty *clone(qpycore_pyqtProperty *orig)
 {
     qpycore_pyqtProperty *pp = (qpycore_pyqtProperty *)PyType_GenericNew(
-            Py_TYPE(orig), 0, 0);
+            Py_TYPE((PyObject *)orig), 0, 0);
 
     if (pp)
     {
index 0dc4987da93e9cd238f7d7cf00ca8293432b973f..440a6d7db02672baf188388763f806d7f9041a16 100644 (file)
@@ -97,7 +97,9 @@ PyQtSlot::Result PyQtSlot::invoke(void **qargs, PyObject *self, void *result,
     else
     {
         // Use the value we have if one wasn't supplied.
-        if (!self)
+        if (self)
+            Py_INCREF(self);
+        else
             self = instance();
 
         // If self is NULL then we didn't have a method in the first place.
@@ -108,12 +110,18 @@ PyQtSlot::Result PyQtSlot::invoke(void **qargs, PyObject *self, void *result,
 
         // See if the instance has gone (which isn't an error).
         if (self == Py_None)
+        {
+            Py_DECREF(self);
             return PyQtSlot::Ignored;
+        }
 
         // If the receiver wraps a C++ object then ignore the call if it no
         // longer exists.
         if (!no_receiver_check && PyObject_TypeCheck(self, sipSimpleWrapper_Type) && !sipGetAddress((sipSimpleWrapper *)self))
+        {
+            Py_DECREF(self);
             return PyQtSlot::Ignored;
+        }
 
         sipMethodDef callable_m;
 
@@ -121,6 +129,7 @@ PyQtSlot::Result PyQtSlot::invoke(void **qargs, PyObject *self, void *result,
         callable_m.pm_self = self;
 
         callable = sipFromMethod(&callable_m);
+        Py_DECREF(self);
     }
 
     // Convert the C++ arguments to Python objects.
@@ -181,7 +190,11 @@ bool PyQtSlot::operator==(PyObject *callable) const
         if (other)
             return false;
 
-        return (mfunc == callable_m.pm_function && instance() == callable_m.pm_self);
+        PyObject *instance_obj = instance();
+        bool res = (mfunc == callable_m.pm_function && instance_obj == callable_m.pm_self);
+        Py_XDECREF(instance_obj);
+
+        return res;
     }
 
     if (!other)
@@ -202,14 +215,30 @@ bool PyQtSlot::operator==(PyObject *callable) const
 }
 
 
-// Get the instance object.
+// Get a strong reference to the instance object, otherwise return NULL or a
+// strong referenc to Py_None.
 PyObject *PyQtSlot::instance() const
 {
+    PyObject *instance_obj;
+
     // Use the weak reference if possible.
     if (mself_wr)
-        return PyWeakref_GetObject(mself_wr);
+    {
+#if PY_VERSION_HEX >= 0x030f0000
+        if (PyWeakref_GetRef(mself_wr, &instance_obj) < 0)
+            instance_obj = NULL;
+#else
+        instance_obj = PyWeakref_GetObject(mself_wr);
+        Py_XINCREF(instance_obj);
+#endif
+    }
+    else
+    {
+        instance_obj = mself;
+        Py_XINCREF(instance_obj);
+    }
 
-    return mself;
+    return instance_obj;
 }
 
 
index f839b3040b59c74bbd2b79af324ed07f122c8b0d..a84cf57dc680894ce9b87c7373fbafff9a5de4d5 100644 (file)
@@ -50,7 +50,7 @@ static int qt_metacall_worker(sipSimpleWrapper *pySelf, PyTypeObject *pytype,
 const QMetaObject *qpycore_qobject_metaobject(sipSimpleWrapper *pySelf,
         sipTypeDef *base)
 {
-    sipWrapperType *wt = (pySelf ? (sipWrapperType *)Py_TYPE(pySelf) : 0);
+    sipWrapperType *wt = (pySelf ? (sipWrapperType *)Py_TYPE((PyObject *)pySelf) : 0);
 
     return qpycore_get_qmetaobject(wt, base);
 }
@@ -64,7 +64,8 @@ int qpycore_qobject_qt_metacall(sipSimpleWrapper *pySelf, sipTypeDef *base,
     if (!pySelf)
         return -1;
 
-    return qt_metacall_worker(pySelf, Py_TYPE(pySelf), base, _c, _id, _a);
+    return qt_metacall_worker(pySelf, Py_TYPE((PyObject *)pySelf), base, _c,
+            _id, _a);
 }
 
 
@@ -220,10 +221,10 @@ bool qpycore_qobject_qt_metacast(sipSimpleWrapper *pySelf,
 
     // We only need to look at the MRO if the object is a wrapped type (rather
     // than a user sub-class).
-    if (base_pytype != Py_TYPE(pySelf))
+    if (base_pytype != Py_TYPE((PyObject *)pySelf))
     {
-        PyObject *mro = PyObject_GetAttr((PyObject *)Py_TYPE(pySelf),
-                qpycore_dunder_mro);
+        PyObject *mro = PyObject_GetAttr(
+                (PyObject *)Py_TYPE((PyObject *)pySelf), qpycore_dunder_mro);
         Q_ASSERT(mro);
 
         for (Py_ssize_t i = 0; i < PyTuple_Size(mro); ++i)